program main
  !================================================================================
  ! 1D linear advection equation: u_t + c u_x = 0
  ! implicit time integration with RK method, and finite difference, uwpind, MCV, 
  ! WENO and TVD for spatial discretization
  ! Author: Jianghao Li, 2025-5-26
  !================================================================================

  use time_mod
  use namelist_mod
  use time_stepping_mod
  use adv_1d_case_mod
  use history_mod
  use butcher_tableau_mod
  use diagnostics_mod
  use boundary_mod
  
  implicit none

  real(r8), allocatable :: fcstvar(:), fcstvar_exact(:)
  character(len=256) :: namelist_path
  logical :: is_exist
  integer :: io_step = 1
  real(r8) t_start, t_end, tm, dt

  call cpu_time(t_start)
  call get_command_argument(1, namelist_path)
  inquire(file=namelist_path, exist=is_exist)
  if (is_exist) then
    call parse_namelist(namelist_path)
  end if

  if (.not. allocated(fcstvar      )) allocate(fcstvar      (1-nhalo:nx+nhalo))
  if (.not. allocated(fcstvar_exact)) allocate(fcstvar_exact(1:nx))

  call butcher_tableau_init()
  call time_stepping_init()
  call history_init()
  call boundary_init()
  call adv_1d_case_init(fcstvar)
  if (trim(space_scheme) == 'MCV') then
    dt = CFL * (0.5 * dx) / abs(u)
  else
    dt = CFL * dx / abs(u)
  end if
  call get_exact_solution(elapsed_seconds, fcstvar_exact)
  call history_output(fcstvar(1:nx), fcstvar_exact, io_step)
  call diagnose_total_mass(fcstvar, tm)

  write(6,100) 'step:', time_step, 'dt=', dt, 'tm=', tm, 't=', elapsed_seconds

  do while (elapsed_seconds < t_final)
    if (elapsed_seconds + dt > t_final) dt = t_final - elapsed_seconds
    call time_integrator(fcstvar, dt)
    call advance_time(dt)
    call get_exact_solution(elapsed_seconds, fcstvar_exact)
    if (mod(time_step, output_interval) == 0) then
      io_step = io_step + 1
      call diagnose_total_mass(fcstvar, tm)
      write(6,100) 'step:', time_step, 'dt=', dt, 'tm=', tm, 't=', elapsed_seconds
      call history_output(fcstvar(1:nx), fcstvar_exact, io_step)
    end if
  end do
100 format(A6, 1X, I5, 1X, A4, 1x, E16.4, 1X, A4, f8.2, 1X, A4, E12.4)  
  
  if (allocated(fcstvar      )) deallocate(fcstvar      )
  if (allocated(fcstvar_exact)) deallocate(fcstvar_exact)
  if (allocated(x      )) deallocate(x)
  call time_stepping_final()
  call butcher_tableau_final()
  call cpu_time(t_end)
  print*, 'CPU time used: ', t_end - t_start

end program main